/* ------------------------------------------------------------
 *  Bunny project - UI
 *
 * ------------------------------------------------------------ 
 */

final int	INDEX_OFFSET	= 20;


final color 	LOW = color(0, 102, 153);
final color	HIGH = color(204, 102, 0);

color colorSteps[] = {
	color(246,	212,	189, 255),
	color(239,	155,	120, 255),
	color(232,	74,	44,  255),
	color(143,	45,	25,  255),
	color(77,	19,	9,   255)
};

color colorScale[] = null;


class Grid
{
	public Grid(DataStore _data, int _x, int _y, int _gridWidth, int _gridHeight)
	{
		data = _data;
		x = _x;
		y = _y;
		gridWidth = _gridWidth;
		gridHeight = _gridHeight;
		
		font = createFont("Helvetica", 20.0);
		
		// calculate size of grid cell
		cellWidth =  (float) (gridWidth - INDEX_OFFSET) / (float) data.getCols();
		cellHeight = (float) (gridHeight - INDEX_OFFSET) / (float) data.getRows();
	
		highlighted = highlightedIndex = null;
		highlightedColor = color(0, 0, 0, 0);
		
		// initialize color scal
	    	if (colorScale == null) {
      
	    	    colorScale = new color[(colorSteps.length - 1)* 50];
	    	    for (int step = 0; step < colorSteps.length - 1; step++)
	    	    {

	    	    	    for (int i = 0; i < 50; i++)
	    	    	    {
	    	    	    	    colorScale[step * 50 + i] = lerpColor(colorSteps[step], colorSteps[step+1], (float) i / 50.0, HSB);
	    	    	    }
	    	    }
	    	}
	    	
	}

	private color calculateColor(float n)
	{
		int index = (int) round( map(n, 0.0, 1.0, 0.0, (float) (colorScale.length - 1)) );
		return colorScale[index];
	}
  
	
	private color drawCell(int row, int col, float _x, float _y, float _width, float _height)
	{
		ArrayList<Float> cell = data.getCell(row, col);
		color c = color(0, 0, 0, 0);
		if (cell.size() == 0)
		{
			noFill();
		}
		else
		{
			float avg = average(cell);
			//c = lerpColor(LOW, HIGH, avg / 100.0);
			c = calculateColor( avg / 100.0 );
			fill(c);
		}
		rect(_x, _y, _width, _height);
		return c;
				
	}
	
	public void render()
	{
		int rows = data.getRows();
		int cols = data.getCols();
		
		
		pushStyle();
		
		// change style
		noFill();
		stroke(50);
		strokeWeight(1.5);
		rectMode(CORNER);

		// highlighted cell
		highlighted = null;
		highlightedIndex = null;
		highlightedColor = color(0);
		
		float curY = (float) (y + INDEX_OFFSET);
		for (int i = 0; i < rows; i++)
		{
			float curX = (float) (x + INDEX_OFFSET);
			for (int j = 0; j < cols; j++)
			{		
				// see if mouse is within rectangle
				boolean mouseIn = mouseX >= curX && mouseX <= curX + cellWidth;
				mouseIn &= mouseY >= curY && mouseY <= curY + cellHeight;
				
				// draw rectangle
				color c = drawCell(i, j, curX, curY, cellWidth, cellHeight);
				if (mouseIn)
				{
					// hilight
					highlighted = new PVector(curX, curY);
					highlightedIndex = new PVector(i, j);
					highlightedColor = c;
				}				
				curX += cellWidth;
			}
			curY += cellHeight;
		}
		
		popStyle();
		
		// render indices
		renderIndices();
		
		// render highlighted
		if (highlighted != null)
		{
			pushStyle();
			{	
				// render highlighted rectangle again
				drawCell(
					(int) highlightedIndex.x, (int) highlightedIndex.y, 
					highlighted.x - 10.0, highlighted.y - 10.0,
					cellWidth + 20.0, cellHeight + 20.0
				);
			}
			popStyle();
		}
	}
	
	private void renderIndices()
	{
		int rows = data.getRows();
		int cols = data.getCols();
		
		pushStyle();
		
		textFont(font);
		fill(0);
		
		// render column indices
		textAlign(CENTER, TOP);
		float _x = x + INDEX_OFFSET;
		for (int i = 0; i < cols; i++)
		{
			char a = (char) ((int)'A' + i);
			String txt = "" + a;
			text(txt, _x + cellWidth / 2.0, y);
			_x += cellWidth;
		}
		
		textAlign(LEFT, CENTER);
		float _y = y + INDEX_OFFSET;
		for (int i = 0; i < rows; i++)
		{
			String txt = "" + (1 + i);
			text(txt, x, _y + cellHeight / 2.0, 0);
			_y += cellHeight;
		}
		
		
		popStyle();
	}
	
	/* private
	 * ---------
	 */
	private int x;
	private int y;
	private int gridWidth;
	private int gridHeight;
	
	private float cellWidth, cellHeight;
	
	// highlighted cell
	PVector highlighted, highlightedIndex;
	color highlightedColor;
	
	// data
	private DataStore data;
	
	// font
	PFont font;
}
